package com.suarte.core.hibernate;

import com.suarte.core.Company;
import com.suarte.core.Contact;
import com.suarte.core.Currency;
import com.suarte.core.DocumentStatus;
import com.suarte.core.Invoice;
import com.suarte.core.InvoicePayment;
import com.suarte.core.Payment;
import com.suarte.core.dao.InvoiceDao;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.appfuse.dao.hibernate.GenericDaoHibernate;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @date   Dec 20, 2010
 * @author Ggutierrez
 */
@Repository("invoiceDao")
public class InvoiceDaoHibernate extends GenericDaoHibernate<Invoice, Long> implements InvoiceDao {

    public InvoiceDaoHibernate() {
        super(Invoice.class);
    }

    public List<Invoice> findByDescription(String description) {
        return getHibernateTemplate().find("from Invoice where description like upper(?)", description.concat("%").toUpperCase());
    }

    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
    public void store(Invoice object) {
        getHibernateTemplate().saveOrUpdate(object);
    }

    @Override
    public Invoice get(Long id) {
        List<Invoice> results = getHibernateTemplate().find("from Invoice this join fetch this.quotation quotation join fetch this.details detail where this.id = ?", id);
        return !results.isEmpty() ? results.get(0) : null;
    }

    public List<Invoice> findInvoices(Long id, Long quotationId, String description, Date date, Company company, Contact contact, DocumentStatus status,
            Date fromExpirationDate, Date toExpirationDate) {
        String hql = "from Invoice this "
                + " join fetch this.company company"
                + " join fetch this.contact contact"
                + " where 1 = 1";
        List args = new ArrayList();

        if (id != null) {
            args.add(id);
            hql += " and this.id = ?";
        }
        if (quotationId != null) {
            args.add(quotationId);
            hql += " and this.quotation.id = ?";
        }
        if (!isBlank(description)) {
            args.add(description.toUpperCase().concat("%"));
            hql += " and upper(ltrim(rtrim(this.description))) like upper(ltrim(rtrim(?)))";
        }
        if (date != null) {
            args.add(date);
            hql += " and (this.date) = (?)";
        }

        if (company != null) {
            args.add(company);
            hql += " and company = ?";
        }

        if (contact != null) {
            args.add(contact);
            hql += " and contact = ?";
        }

        if (status != null) {
            args.add(status);
            hql += " and this.status = ?";
        }

        if (fromExpirationDate != null) {
            args.add(fromExpirationDate);
            hql += " and (this.expirationDate) >= (?)";
        }

        if (toExpirationDate != null) {
            args.add(toExpirationDate);
            hql += " and (this.expirationDate) <= (?)";
        }

        List results = getHibernateTemplate().find(hql, args.toArray());
        return results;
    }

    public List<Invoice> findPendingInvoices(Company company, Currency currency) {
        String hql = "from Invoice this "
                + " join fetch this.company company"
                + " where this.status in ('ACTIVA','PAGADA_PARCIAL') ";
        List args = new ArrayList();

        if (company != null) {
            args.add(company);
            hql += " and company = ?";
        }
        
        if (currency != null) {
            args.add(currency);
            hql += " and this.currency = ?";
        }

        List results = getHibernateTemplate().find(hql, args.toArray());
        return results;
    }

    private boolean isBlank(String value) {
        return value == null || value.trim().length() == 0;
    }

    public List<InvoicePayment> findInvoiceByPayment(Payment payment) {
        String hql = "from InvoicePayment this "
                + " join fetch this.invoice invoice"
                + " join fetch this.payment payment where 1 = 1";
        List args = new ArrayList();

        if (payment != null) {
            args.add(payment);
            hql += " and payment = ?";
        }

        List results = getHibernateTemplate().find(hql, args.toArray());
        return results;
    }
}
